home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 23 / AACD 23.iso / AACD / Online / opennap / util.c < prev    next >
C/C++ Source or Header  |  2001-06-08  |  10KB  |  477 lines

  1. /* Copyright (C) 2000-1 drscholl@users.sourceforge.net
  2.    This is free software distributed under the terms of the
  3.    GNU Public License.  See the file COPYING for details.
  4.  
  5.    $Id: util.c,v 1.98 2001/02/15 08:39:45 drscholl Exp $
  6.  
  7.    This file contains various utility functions useful elsewhere in this
  8.    server */
  9.  
  10. /* Modified 29/05/01 : init_random() modified to remove dependency on the
  11.       for Amiga port : structure "global", which doesn't exist in Amiga GCC
  12.                        2.7.0
  13. */                     
  14.  
  15. #include <fcntl.h>
  16. #include <stdarg.h>
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include <errno.h>
  20. #include <ctype.h>
  21. #ifndef WIN32
  22. #include <unistd.h>
  23. #include <sys/time.h>
  24. #endif
  25. #include <stdlib.h>
  26. #include <sys/socket.h>
  27. #include <netinet/in.h>
  28. #include <arpa/inet.h>
  29.  
  30. #include "md5.h"
  31. #include "opennap.h"
  32. #include "debug.h"
  33.  
  34. /* writes `val' as a two-byte value in little-endian format */
  35. void
  36. set_val (char *d, unsigned short val)
  37. {
  38.     val = BSWAP16 (val);
  39.     memcpy (d, &val, 2);
  40. }
  41.  
  42. /* this is like strtok(2), except that all fields are returned as once.  nul
  43.    bytes are written into `pkt' and `template' is updated with pointers to
  44.    each field in `pkt' */
  45. /* returns: number of fields found. */
  46. int
  47. split_line (char **template, int templatecount, char *pkt)
  48. {
  49.     int     i = 0;
  50.  
  51.     if (!pkt)
  52.         return -1;
  53.     while (ISSPACE (*pkt))
  54.         pkt++;
  55.     while (*pkt && i < templatecount)
  56.     {
  57.         if (*pkt == '"')
  58.         {
  59.             /* quoted string */
  60.             pkt++;
  61.             template[i++] = pkt;
  62.             pkt = strchr (pkt, '"');
  63.             if (!pkt)
  64.             {
  65.                 /* bogus line */
  66.                 return -1;
  67.             }
  68.             *pkt++ = 0;
  69.             if (!*pkt)
  70.                 break;
  71.             pkt++;              /* skip the space */
  72.         }
  73.         else
  74.         {
  75.             template[i++] = pkt;
  76.             pkt = strpbrk (pkt, " \t\r\n");
  77.             if (!pkt)
  78.                 break;
  79.             *pkt++ = 0;
  80.         }
  81.         while (ISSPACE (*pkt))
  82.             pkt++;
  83.     }
  84.     return i;
  85. }
  86.  
  87. static char hex[] = "0123456789ABCDEF";
  88.  
  89. void
  90. expand_hex (char *v, int vsize)
  91. {
  92.     int     i;
  93.  
  94.     for (i = vsize - 1; i >= 0; i--)
  95.     {
  96.         v[2 * i + 1] = hex[v[i] & 0xf];
  97.         v[2 * i] = hex[(v[i] >> 4) & 0xf];
  98.     }
  99. }
  100.  
  101. void
  102. init_random (void)
  103. {
  104.     /*ASSERT (global.current_time != 0);*/
  105.     /* force generation of a different seed if respawning quickly by adding
  106.        the pid of the current process */
  107.     srand (/*global.current_time + */time(NULL) + getuid () + getpid ());
  108. }
  109.  
  110. void
  111. get_random_bytes (char *d, int dsize)
  112. {
  113.     int     i = 0, v;
  114.  
  115.     while (i < dsize)
  116.     {
  117.         v = rand ();
  118.         d[i++] = v & 0xff;
  119.         if (i < dsize)
  120.             d[i++] = (v >> 8) & 0xff;
  121.         if (i < dsize)
  122.             d[i++] = (v >> 16) & 0xff;
  123.         if (i < dsize)
  124.             d[i++] = (v >> 24) & 0xff;
  125.     }
  126. }
  127.  
  128.     /* generate our own nonce value */
  129. char   *
  130. generate_nonce (void)
  131. {
  132.     char   *nonce;
  133.  
  134.     nonce = MALLOC (17);
  135.     if (!nonce)
  136.     {
  137.         OUTOFMEMORY ("generate_nonce");
  138.         return 0;
  139.     }
  140.     nonce[16] = 0;
  141.  
  142.     get_random_bytes (nonce, 8);
  143.  
  144.     /* expand the binary data into hex for transport */
  145.     expand_hex (nonce, 8);
  146.  
  147.     return nonce;
  148. }
  149.  
  150. CHANNEL *
  151. new_channel (void)
  152. {
  153.     CHANNEL *c = CALLOC (1, sizeof (CHANNEL));
  154.  
  155.     if (!c)
  156.     {
  157.         OUTOFMEMORY ("new_channel");
  158.         return 0;
  159.     }
  160. #ifdef DEBUG
  161.     c->magic = MAGIC_CHANNEL;
  162. #endif
  163.     return c;
  164. }
  165.  
  166. char   *
  167. strfcpy (char *dest, const char *src, size_t destlen)
  168. {
  169.     strncpy (dest, src, destlen);
  170.     dest[destlen - 1] = 0;
  171.     return dest;
  172. }
  173.  
  174. #if LOG_CHANNEL
  175. static int Logging = 0;
  176. #endif
  177.  
  178. void
  179. log (const char *fmt, ...)
  180. {
  181.     va_list ap;
  182.  
  183. #if LOG_CHANNEL
  184.     char    buf[1024];
  185.     int     len;
  186.     char   *msg;
  187.  
  188.     strfcpy (buf + 4, "&LOG opennap ", sizeof (buf) - 4);
  189.     len = strlen (buf + 4);
  190.     msg = buf + len + 4;
  191.     va_start (ap, fmt);
  192.     vsnprintf (buf + 4 + len, sizeof (buf) - 4 - len, fmt, ap);
  193.     va_end (ap);
  194.  
  195.     /* prevent infinite loop */
  196.     if (!Logging)
  197.     {
  198.         len += strlen (buf + 4 + len);
  199.         set_tag (buf, MSG_SERVER_PUBLIC);
  200.         set_len (buf, len);
  201.  
  202.         Logging = 1;
  203.         (void) send_to_channel ("&LOG", buf, len + 4);
  204.         Logging = 0;
  205.     }
  206.  
  207.     /* display log msg on console */
  208.     fputs (msg, stdout);
  209. #else
  210.     va_start (ap, fmt);
  211.     vprintf (fmt, ap);
  212.     va_end (ap);
  213. #endif
  214.     fputc ('\n', stdout);
  215.     fflush (stdout);
  216. }
  217.  
  218. /* like next_arg(), except we don't skip over additional whitespace */
  219. char   *
  220. next_arg_noskip (char **s)
  221. {
  222.     char   *r = *s;
  223.  
  224.     *s = strchr (r, ' ');
  225.     if (*s)
  226.         *(*s)++ = 0;
  227.     return r;
  228. }
  229.  
  230. char   *
  231. next_arg (char **s)
  232. {
  233.     char   *r = *s;
  234.  
  235.     if (!r)
  236.         return 0;
  237.     while (ISSPACE (*r))
  238.         r++;
  239.     if (!*r)
  240.         return 0;
  241.     if (*r == '"')
  242.     {
  243.         r++;
  244.         *s = strchr (r, '"');
  245.     }
  246.     else
  247.         *s = strpbrk (r, " \t\r\n");
  248.     if (*s)
  249.     {
  250.         *(*s)++ = 0;
  251.         while (ISSPACE (**s))
  252.             ++ * s;
  253.         if (!**s)
  254.             *s = 0;             /* no more arguments */
  255.     }
  256.     return r;
  257. }
  258.  
  259. char   *
  260. strlower (char *s)
  261. {
  262.     char   *r = s;
  263.  
  264.     ASSERT (s != 0);
  265.     while (*s)
  266.         *s++ = tolower ((unsigned char) *s);
  267.     return r;
  268. }
  269.  
  270. int
  271. safe_realloc (void **ptr, int bytes)
  272. {
  273.     void   *t;
  274.  
  275.     t = REALLOC (*ptr, bytes);
  276.     if (!t)
  277.         return -1;
  278.     *ptr = t;
  279.     return 0;
  280. }
  281.  
  282. void
  283. print_args (int ac, char **av)
  284. {
  285.     int     i;
  286.  
  287.     printf ("print_args(): [%d]", ac);
  288.     for (i = 0; i < ac; i++)
  289.         printf (" \"%s\"", av[i]);
  290.     fputc ('\n', stdout);
  291. }
  292.  
  293. static char alphabet[] =
  294.  
  295.     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  296. #define alphabet(c) alphabet[(unsigned int)c]
  297.  
  298. static int
  299. b64_encode (char *out, int *outsize, char *in, int insize)
  300. {
  301.     unsigned char a, b, c, d;
  302.     char   *pout = out;
  303.  
  304.     while (insize > 0)
  305.     {
  306.         c = d = 0xff;
  307.         a = (*in >> 2) & 0x3f;
  308.         b = (*in & 0x3) << 4;
  309.         in++;
  310.         insize--;
  311.         if (insize)
  312.         {
  313.             b |= (*in >> 4) & 0xf;
  314.             c = (*in & 0xf) << 2;
  315.             in++;
  316.             insize--;
  317.             if (insize)
  318.             {
  319.                 c |= (*in >> 6) & 0x3;
  320.                 d = *in & 0x3f;
  321.                 in++;
  322.                 insize--;
  323.             }
  324.         }
  325.         *out++ = alphabet (a);
  326.         *out++ = alphabet (b);
  327.         if (c != 0xff)
  328.         {
  329.             *out++ = alphabet (c);
  330.             if (d != 0xff)
  331.                 *out++ = alphabet (d);
  332.             else
  333.                 *out++ = '=';
  334.         }
  335.         else
  336.         {
  337.             *out++ = '=';
  338.             *out++ = '=';
  339.         }
  340.     }
  341.     *out = 0;
  342.     *outsize = out - pout;
  343.     return 0;
  344. }
  345.  
  346. static char b64_lookup[128] = {
  347.     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  348.     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  349.     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
  350.     52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
  351.     -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
  352.     15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
  353.     -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
  354.     41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1
  355. };
  356.  
  357. #define b64_lookup(c) b64_lookup[(unsigned int)c]
  358.  
  359. static int
  360. b64_decode (char *out, int *outsize, const char *in)
  361. {
  362.     unsigned char a, b, c, d;
  363.     unsigned char b2, b3;
  364.     char   *pout = out;
  365.  
  366.     while (*in)
  367.     {
  368.         a = b64_lookup (*in++);
  369.         b = b64_lookup (*in++);
  370.         *out++ = a << 2 | b >> 4;
  371.         b2 = b << 4;
  372.         if (*in && *in != '=')
  373.         {
  374.             c = b64_lookup (*in++);
  375.             b2 |= c >> 2;
  376.             *out++ = b2;
  377.             b3 = c << 6;
  378.             if (*in && *in != '=')
  379.             {
  380.                 d = b64_lookup (*in++);
  381.                 b3 |= d;
  382.                 *out++ = b3;
  383.             }
  384.             else
  385.                 break;
  386.         }
  387.         else
  388.             break;
  389.     }
  390.     *outsize = out - pout;
  391.     return 0;
  392. }
  393.  
  394. int
  395. check_pass (const char *info, const char *pass)
  396. {
  397.     struct md5_ctx md;
  398.     char    hash[16], real[16];
  399.     int     realsize;
  400.  
  401.     ASSERT (info != 0);
  402.     ASSERT (pass != 0);
  403.     if (*info != '1' || *(info + 1) != ',')
  404.         return -1;
  405.     info += 2;
  406.     md5_init_ctx (&md);
  407.     md5_process_bytes (info, 8, &md);
  408.     info += 8;
  409.     if (*info != ',')
  410.         return -1;
  411.     info++;
  412.     md5_process_bytes (pass, strlen (pass), &md);
  413.     md5_finish_ctx (&md, hash);
  414.     realsize = sizeof (real);
  415.     b64_decode (real, &realsize, info);
  416.     ASSERT (realsize == 16);
  417.     if (memcmp (real, hash, 16) == 0)
  418.         return 0;
  419.     return -1;
  420. }
  421.  
  422. char   *
  423. generate_pass (const char *pass)
  424. {
  425.     struct md5_ctx md;
  426.     char    hash[16];
  427.     char    output[36];         /* 1,xxxxxxxx,xxxxxxxxxxxxxxxxxxxxxxx== */
  428.     int     outsize;
  429.     int     i;
  430.  
  431.     ASSERT (pass != 0);
  432.     output[0] = '1';
  433.     output[1] = ',';
  434.     get_random_bytes (output + 2, 8);
  435.     for (i = 0; i < 8; i++)
  436.         output[i + 2] = alphabet[((unsigned int) output[i + 2]) % 64];
  437.     output[10] = ',';
  438.     md5_init_ctx (&md);
  439.     md5_process_bytes (output + 2, 8, &md);
  440.     md5_process_bytes (pass, strlen (pass), &md);
  441.     md5_finish_ctx (&md, hash);
  442.     outsize = sizeof (output) - 11;
  443.     b64_encode (output + 11, &outsize, hash, 16);
  444.     output[sizeof (output) - 3] = 0;    /* strip the trailing == */
  445.     return (STRDUP (output));
  446. }
  447.  
  448. CHANNEL *
  449. find_channel (LIST * channels, const char *s)
  450. {
  451.     for (; channels; channels = channels->next)
  452.         if (!strcasecmp (((CHANNEL *) channels->data)->name, s))
  453.             return channels->data;
  454.     return 0;
  455. }
  456.  
  457. void
  458. free_pointer (void *p)
  459. {
  460.     FREE (p);
  461. }
  462.  
  463. /* check to make sure this string is a valid host name.  include the glob
  464.  * characters
  465.  */
  466. int
  467. invalid_host (const char *p)
  468. {
  469.     while (*p)
  470.     {
  471.         if (!isalnum (*p) || !strchr (".-?*", *p))
  472.             return 1;
  473.         p++;
  474.     }
  475.     return 0;
  476. }
  477.